import { Injectable, Logger } from '@nestjs/common';
import * as puppeteer from 'puppeteer';
import {
  ICrawler,
  NovelInfo,
  ChapterInfo,
  ChapterContent,
} from '../interfaces/crawler.interface';

@Injectable()
export class QidianCrawlerV3 implements ICrawler {
  private readonly logger = new Logger(QidianCrawlerV3.name);
  private browser: puppeteer.Browser;

  async initBrowser() {
    if (!this.browser) {
      const executablePath =
        process.env.CHROME_EXECUTABLE_PATH ||
        'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';

      this.browser = await puppeteer.launch({
        headless: true,
        executablePath,
        args: [
          '--no-sandbox',
          '--disable-setuid-sandbox',
          '--disable-web-security',
          '--disable-blink-features=AutomationControlled',
          '--disable-features=VizDisplayCompositor',
        ],
      });
    }
  }

  getSource(): string {
    return 'qidian';
  }

  validateUrl(url: string): boolean {
    return url.includes('qidian.com');
  }

  async getNovelInfo(url: string): Promise<NovelInfo> {
    await this.initBrowser();
    const page = await this.browser.newPage();

    try {
      // 设置更真实的浏览器特征
      await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      );
      await page.setViewport({ width: 1920, height: 1080 });

      // 移除webdriver标识
      await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined,
        });
        // 修改navigator.plugins
        Object.defineProperty(navigator, 'plugins', {
          get: () => [1, 2, 3, 4, 5],
        });
        // 修改navigator.languages
        Object.defineProperty(navigator, 'languages', {
          get: () => ['zh-CN', 'zh', 'en'],
        });
      });

      this.logger.log(`开始访问起点页面: ${url}`);

      // 先访问页面等待加载
      await page.goto(url, {
        waitUntil: 'domcontentloaded',
        timeout: 30000,
      });

      // 等待页面完全加载
      await new Promise((resolve) => setTimeout(resolve, 8000));

      // 检查是否需要跳转到其他页面
      const currentUrl = page.url();
      this.logger.log(`当前页面URL: ${currentUrl}`);

      // 提取小说基本信息
      const novelInfo = await page.evaluate(() => {
        const result = {
          title: '',
          author: '',
          cover: '',
          description: '',
          category: '',
          wordCount: '',
          status: 0,
          updateTime: '',
          chapterList: [] as any[],
        };

        // 多种标题选择器
        const titleSelectors = [
          '.book-info__title',
          'h1.book-name',
          '.book-name',
          'h1',
          '.title',
          '.book-title',
          '[class*="title"]',
          '.name',
          '.elfsight-title',
          '.work-title',
          '.detail-title',
        ];

        for (const selector of titleSelectors) {
          const elements = document.querySelectorAll(selector);
          for (const element of elements) {
            const text = element.textContent?.trim();
            if (
              text &&
              text.length > 0 &&
              !text.includes('起点') &&
              text.length < 50
            ) {
              result.title = text;
              break;
            }
          }
          if (result.title) break;
        }

        // 如果还是没找到标题，尝试从页面标题提取
        if (!result.title) {
          const pageTitle = document.title;
          const cleanTitle = pageTitle.replace(/[-_|].*$/, '').trim();
          if (cleanTitle && cleanTitle.length < 50) {
            result.title = cleanTitle;
          }
        }

        // 多种作者选择器
        const authorSelectors = [
          '.book-info__author__name',
          '.author',
          '.book-author',
          '[class*="author"]',
          'a[href*="author"]',
          '.writer',
          '.book-writer',
          '.author-name',
          '.by-author',
        ];

        for (const selector of authorSelectors) {
          const elements = document.querySelectorAll(selector);
          for (const element of elements) {
            let authorText = element.textContent?.trim();
            if (authorText && authorText.length > 0 && authorText.length < 30) {
              // 清理作者名称
              authorText = authorText
                .replace(/^作者[:：]\s*/, '')
                .replace(/^写手[:：]\s*/, '');
              if (
                !authorText.includes('起点') &&
                !authorText.includes('中文网')
              ) {
                result.author = authorText;
                break;
              }
            }
          }
          if (result.author) break;
        }

        // 封面图片选择器
        const coverSelectors = [
          '.book-info__cover img',
          '.book-cover img',
          '.cover img',
          'img[src*="cover"]',
          'img[alt*="封面"]',
          '.book-img img',
          '.detail-cover img',
          'img[src*="qdbimg"]',
        ];

        for (const selector of coverSelectors) {
          const element = document.querySelector(selector) as HTMLImageElement;
          if (element && element.src && element.src.includes('http')) {
            result.cover = element.src;
            break;
          }
        }

        // 小说简介选择器
        const descSelectors = [
          '.book-info__intro',
          '.book-intro',
          '.intro',
          '.description',
          '[class*="intro"]',
          '[class*="desc"]',
          '.book-desc',
          '.detail-desc',
          '.summary',
        ];

        for (const selector of descSelectors) {
          const element = document.querySelector(selector);
          if (element && element.textContent) {
            const text = element.textContent.trim();
            if (text.length > 20 && text.length < 2000) {
              result.description = text;
              break;
            }
          }
        }

        // 获取分类、状态、字数等信息
        const infoSelectors = [
          '.book-info__row li',
          '.book-info-detail li',
          '[class*="info"] li',
          '.detail li',
          '.meta-info li',
          '.book-meta li',
        ];

        const infoTexts: string[] = [];
        for (const selector of infoSelectors) {
          const elements = document.querySelectorAll(selector);
          elements.forEach((element) => {
            const text = element.textContent?.trim();
            if (text && text.length > 0 && text.length < 100) {
              infoTexts.push(text);
            }
          });
        }

        // 解析信息
        infoTexts.forEach((text) => {
          // 分类
          if (
            !result.category &&
            (text.includes('类型') ||
              text.includes('分类') ||
              text.includes('类别'))
          ) {
            const categoryMatch = text.match(/[:：]\s*(.+)/);
            if (categoryMatch) result.category = categoryMatch[1].trim();
          }

          // 状态
          if (text.includes('完结') || text.includes('已完结')) {
            result.status = 1;
          } else if (text.includes('连载') || text.includes('连载中')) {
            result.status = 0;
          }

          // 字数
          if (!result.wordCount && text.includes('万') && text.includes('字')) {
            result.wordCount = text;
          }

          // 更新时间
          if (
            !result.updateTime &&
            (text.includes('更新') || /\d{4}-\d{2}-\d{2}/.test(text))
          ) {
            result.updateTime = text;
          }
        });

        return result;
      });

      this.logger.log(
        `起点基本信息提取结果: 标题="${novelInfo.title}", 作者="${novelInfo.author}"`,
      );

      // 获取章节列表
      let chapters: ChapterInfo[] = [];

      // 首先尝试在当前页面查找章节链接
      chapters = await this.extractChaptersFromPage(page);

      // 如果当前页面没有章节，尝试跳转到目录页面
      if (chapters.length === 0) {
        chapters = await this.extractChaptersFromCatalog(page, url);
      }

      this.logger.log(`起点章节提取结果: 找到${chapters.length}个章节`);

      // 构建最终返回对象
      const finalNovelInfo: NovelInfo = {
        title: novelInfo.title || '未知标题',
        author: novelInfo.author || '未知作者',
        cover: novelInfo.cover || '',
        description: novelInfo.description || '',
        category: novelInfo.category || '其他',
        wordCount: novelInfo.wordCount || '',
        status: novelInfo.status,
        updateTime: novelInfo.updateTime || '',
        chapterList: chapters.slice(0, 100), // 增加章节限制
      };

      return finalNovelInfo;
    } catch (error) {
      this.logger.error(`解析起点小说失败: ${error.message}`, error.stack);
      throw new Error('解析起点小说失败');
    } finally {
      await page.close();
    }
  }

  private async extractChaptersFromPage(
    page: puppeteer.Page,
  ): Promise<ChapterInfo[]> {
    try {
      return await page.evaluate(() => {
        const chapters: ChapterInfo[] = [];

        // 更多章节链接选择器
        const chapterSelectors = [
          'a[href*="chapter"]',
          'a[href*="/read/"]',
          '.chapter-item a',
          '.chapter a',
          '[class*="chapter"] a',
          '.catalog-list a',
          '.directory-list a',
          '.volume-list a',
          '.chapter-list a',
          'a[title*="章"]',
        ];

        for (const selector of chapterSelectors) {
          const elements = document.querySelectorAll(selector);
          if (elements.length > 0) {
            let chapterIndex = 1;
            elements.forEach((element, index) => {
              const title = element.textContent?.trim();
              const href = (element as HTMLAnchorElement).href;

              if (
                title &&
                href &&
                (title.includes('第') || title.includes('章'))
              ) {
                chapters.push({
                  title,
                  url: href,
                  index: chapterIndex++,
                  isFree: true, // 默认免费，后续可以进一步判断
                  content: '',
                  volumeName: '正文',
                });
              }
            });

            if (chapters.length > 0) break;
          }
        }

        return chapters;
      });
    } catch (error) {
      this.logger.warn(`从页面提取章节失败: ${error.message}`);
      return [];
    }
  }

  private async extractChaptersFromCatalog(
    page: puppeteer.Page,
    originalUrl: string,
  ): Promise<ChapterInfo[]> {
    try {
      // 从URL提取书籍ID
      const bookIdMatch = originalUrl.match(/\/(\d+)/);
      if (!bookIdMatch) {
        this.logger.warn('无法从URL提取书籍ID');
        return [];
      }

      const bookId = bookIdMatch[1];
      // 尝试多种可能的目录页面URL格式
      const catalogUrls = [
        `https://www.qidian.com/book/${bookId}/catalog`,
        `https://book.qidian.com/book/${bookId}`,
        `https://www.qidian.com/book/${bookId}`,
        `https://qidian.com/book/${bookId}/catalog`,
      ];

      for (const catalogUrl of catalogUrls) {
        try {
          this.logger.log(`尝试访问目录页面: ${catalogUrl}`);

          await page.goto(catalogUrl, {
            waitUntil: 'domcontentloaded',
            timeout: 30000,
          });

          await new Promise((resolve) => setTimeout(resolve, 5000));

          const chapters = await page.evaluate(() => {
            const chapters: ChapterInfo[] = [];

            // 查找卷名和章节的各种选择器
            const volumeSelectors = [
              '.volume-wrap',
              '.volume',
              '[class*="volume"]',
              '.catalog-volume',
              '.directory-volume',
              '.book-volume',
              '.cf',
            ];

            let globalChapterIndex = 1;

            for (const volSelector of volumeSelectors) {
              const volumeElements = document.querySelectorAll(volSelector);

              volumeElements.forEach((volumeElement) => {
                let currentVolumeName = '正文';

                // 查找卷名
                const volumeNameElement = volumeElement.querySelector(
                  '.volume-name, [class*="volume-name"], .vol-name, .catalog-title, .directory-title',
                );
                if (volumeNameElement && volumeNameElement.textContent) {
                  currentVolumeName = volumeNameElement.textContent.trim();
                }

                // 在该卷下查找章节
                const chapterSelectors = [
                  'a[href*="chapter"]',
                  '.chapter-item a',
                  '[class*="chapter"] a',
                  '.catalog-chapter a',
                  'a[href*="/read/"]',
                  '.chapter a',
                ];

                for (const chapSelector of chapterSelectors) {
                  const chapterElements =
                    volumeElement.querySelectorAll(chapSelector);

                  chapterElements.forEach((element) => {
                    const title = element.textContent?.trim();
                    const href = (element as HTMLAnchorElement).href;

                    if (
                      title &&
                      href &&
                      (title.includes('第') || title.includes('章'))
                    ) {
                      chapters.push({
                        title,
                        url: href,
                        index: globalChapterIndex++,
                        isFree: true,
                        content: '',
                        volumeName: currentVolumeName,
                      });
                    }
                  });
                }
              });
            }

            // 如果没有找到卷结构，尝试直接查找章节
            if (chapters.length === 0) {
              const directChapterSelectors = [
                'a[href*="chapter"]',
                'a[href*="/read/"]',
                '.chapter-item a',
                '[class*="chapter"] a',
                'a[title*="章"]',
              ];

              for (const selector of directChapterSelectors) {
                const elements = document.querySelectorAll(selector);

                elements.forEach((element, index) => {
                  const title = element.textContent?.trim();
                  const href = (element as HTMLAnchorElement).href;

                  if (
                    title &&
                    href &&
                    (title.includes('第') || title.includes('章'))
                  ) {
                    chapters.push({
                      title,
                      url: href,
                      index: index + 1,
                      isFree: true,
                      content: '',
                      volumeName: '正文',
                    });
                  }
                });

                if (chapters.length > 0) break;
              }
            }

            return chapters;
          });

          if (chapters.length > 0) {
            this.logger.log(`从目录页面成功提取到${chapters.length}个章节`);
            return chapters;
          }
        } catch (error) {
          this.logger.warn(`访问目录页面 ${catalogUrl} 失败: ${error.message}`);
          continue;
        }
      }

      this.logger.warn('所有目录页面都无法获取到章节信息');
      return [];
    } catch (error) {
      this.logger.error(`从目录页面提取章节失败: ${error.message}`);
      return [];
    }
  }

  async getChapterContent(chapterUrl: string): Promise<ChapterContent> {
    await this.initBrowser();
    const page = await this.browser.newPage();

    try {
      await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      );
      await page.goto(chapterUrl, { waitUntil: 'domcontentloaded' });

      const content = await page.evaluate(() => {
        const title =
          document
            .querySelector('h1, .chapter-title, [class*="title"]')
            ?.textContent?.trim() || '';

        // 多种内容选择器
        const contentSelectors = [
          '.chapter-content',
          '.content',
          '[class*="content"]',
          '.text',
          '[class*="text"]',
          '.read-content',
          '.article-content',
          '.chapter-text',
        ];

        let content = '';
        for (const selector of contentSelectors) {
          const element = document.querySelector(selector);
          if (element && element.textContent) {
            content = element.textContent.trim();
            if (content.length > 100) break;
          }
        }

        return { title, content };
      });

      return {
        title: content.title,
        content: content.content,
        index: 0,
      };
    } finally {
      await page.close();
    }
  }

  async onModuleDestroy() {
    if (this.browser) {
      await this.browser.close();
    }
  }
}
